package com.farm.common.util;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.farm.common.config.JwtConfig;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

@Component
@Data
public class JwtTokenUtil {
    private static final Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);

    public static final String SUBJECT = "sub"; // 签名主题 farm用户ID
    public static final String USER_CATEGORY = "uct"; // 用户分类

    private final JwtConfig jwtConfig;

    /**
     * 根据用户信息生成token
     */
    public String generateToken(Integer userId) {
        byte[] key = jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8);

        return JWT.create()
                .setPayload(SUBJECT, userId)
                .setPayload("jti", RandomUtil.randomString(16))
                .setPayload("prv", null)
                .setPayload(USER_CATEGORY, 1)
                .setIssuer(jwtConfig.getIssuer())
                // .setAudience(jwtConfig.getAudience())
                // 设置签发时间
                .setIssuedAt(DateUtil.date())
                .setNotBefore(DateUtil.date())
                .setExpiresAt(DateUtil.date().offset(DateField.MINUTE,jwtConfig.getTokenExpireTime()))
                .setKey(key)
                .setSigner(JWTSignerUtil.hs256(key))
                .sign();
    }

    /**
     * 从token中获取JWT中的有效载荷
     */
    public JWT parseToken(String token) {
        if (ObjectUtil.isEmpty(token)){
            throw new RuntimeException("非法访问：token 不能为空");
        }else if (token.startsWith(jwtConfig.getTokenHeaderPrefix()) && token.contains(jwtConfig.getTokenHeaderPrefix()+" ")){
            token = token.replace(jwtConfig.getTokenHeaderPrefix()+" ", "");
        }else{
            throw new RuntimeException("非法访问：token 不正确");
        }
        // TODO token 转换(短的转成长度)
        byte[] key = jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8);

        JWT jwt = JWT.of(token).setKey(key).setSigner(JWTSignerUtil.hs256(key));
        if (!jwt.verify()){
            throw new RuntimeException("非法访问：token 错误");
        }
        if (!jwt.validate(0)){
            throw new RuntimeException("非法访问：token 已经过期");
        }

        return jwt;
    }

    /**
     * 从token中获取登录用户Id
     */
    public Integer getUserIdToken(String token) {
        Integer userId = null;
        try{
            JWT jwt = parseToken(token);
            userId = Integer.parseInt(jwt.getPayload(SUBJECT).toString());
        }catch (RuntimeException exception){
            System.out.println(exception.getMessage());
        }

        return userId;
    }

}
